package com.datoucai.controller;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.datoucai.dto.ExportSensitiveWordDto;
import com.datoucai.dto.SensitiveWordDto;
import com.datoucai.entity.TbSensitiveWordsExample;
import com.datoucai.param.AddSensitiveWordParam;
import com.datoucai.param.BaseResult;
import com.datoucai.service.ISensitiveService;
import com.datoucai.utils.BaseResultUtils;
import com.datoucai.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 敏感词
 */
@RestController
@RequestMapping("/sensitivewords")
@Slf4j
public class SensitiveWordsController {

	@Autowired
	ISensitiveService sensitiveService;

	/**
	 * 导出数据上限1000
	 */
	private static final Integer EXPORT_NUM_LIMIT = 1000;

	/**
	 * 导出Excel文档后缀
	 */
	private static final String EXCEL_SUFFIX = ".xlsx";

	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public BaseResult<Boolean> addSensitiveWord(@RequestBody AddSensitiveWordParam param) {
		try {
			log.info("增加敏感词-controller层-入参：{}", JSON.toJSONString(param));
			// 参数校验
			checkParam(param);
			SensitiveWordDto sensitiveWordDto = new SensitiveWordDto();
			sensitiveWordDto.setWord(param.getWord());
			sensitiveWordDto.setCategory(param.getCategory());
			// 敏感词落库
			int count = sensitiveService.insert(sensitiveWordDto);
			log.info("增加敏感词-controller层-出参：{}", count);
			return BaseResultUtils.generateSuccess(count > 0);
		} catch (Exception e) {
			log.error("增加敏感词-controller层-addSensitiveWord-异常：：{}", e);
			return BaseResultUtils.generateFail("新增敏感词异常：" + e.getMessage());
		}
	}

	/**
	 * 导入敏感词
	 * @param file
	 * @return
	 */
	@RequestMapping(value = "/import", method = RequestMethod.POST)
	public BaseResult<Boolean> importWords(@RequestBody MultipartFile file) {
		try {
			InputStream inputStream = file.getInputStream();
			ExcelReader excelReader = ExcelUtil.getReader(inputStream);
			List<List<Object>> list = excelReader.read(1);
			int total = 0;
			for (int i = 0; i < list.size(); i++) {
				List<Object> rows = list.get(i);
				SensitiveWordDto sensitiveWordDto = new SensitiveWordDto();
				sensitiveWordDto.setWord(rows.get(0).toString());
				sensitiveWordDto.setCategory(rows.get(1).toString());
				int count = sensitiveService.insert(sensitiveWordDto);
				total += count;
			}
			log.info("批量导入敏感词-controller层-importWords-插入敏感词数量：{}", total);
			return BaseResultUtils.generateSuccess(total > 0);
		} catch (IOException e) {
			log.error("批量导入敏感词-controller层-importWords-异常：{}", e);
			return BaseResultUtils.generateFail("导入失败，请联系系统管理员" + e.getMessage());
		}
	}

	/**
	 * 导出敏感词
	 * @param response
	 * @return
	 */
	@Deprecated
	@RequestMapping(value = "/exportOld", method = RequestMethod.GET)
	public BaseResult<Boolean> exportWordsOld(HttpServletResponse response) {
		try {
			TbSensitiveWordsExample example = new TbSensitiveWordsExample();
			example.setLimit(1000);
			// 查询数据
			List<SensitiveWordDto> sensitiveWordDtos = sensitiveService.queryByParam(example);

			ExcelWriter writer = ExcelUtil.getWriter();
			writer.write(sensitiveWordDtos, true);

			response.setContentType("application/vnd.ms-excel;charset=utf-8");
			response.setHeader("Content-Disposition", "attachment;filename=sensitiveWords.xlsx");

			ServletOutputStream outputStream = response.getOutputStream();
			writer.flush(outputStream);
			writer.close();

			return BaseResultUtils.generateSuccess(true);
		} catch (Exception e) {
			log.error("批量导出敏感词-controller层-exportWords-异常", e);
			return BaseResultUtils.generateFail("导出失败，请联系系统管理员" + e.getMessage());
		}
	}

	/**
	 * 导出敏感词
	 * @param response
	 * @return
	 */
	@Deprecated
	@RequestMapping(value = "/export", method = RequestMethod.GET)
	public void exportWords(@RequestParam(value = "category", required = false) String category, HttpServletResponse response) {
		try {
			TbSensitiveWordsExample example = new TbSensitiveWordsExample();
			TbSensitiveWordsExample.Criteria criteria = example.createCriteria();
			if (StringUtils.isNotBlank(category)) {
				criteria.andCategoryEqualTo(category);
			}
			example.setLimit(EXPORT_NUM_LIMIT);

			// 查询数据
			List<SensitiveWordDto> sensitiveWordDtos = sensitiveService.queryByParam(example);
			List<ExportSensitiveWordDto> exportSensitiveWordDtos = buildExportSensitiveWordDto(sensitiveWordDtos);

			response.setContentType("application/vnd.ms-excel;charset=utf-8");
			response.setCharacterEncoding("utf-8");
			// 文件名
			String fileName = URLEncoder.encode("导出敏感词" + DateUtils.getCurrentTimeStr() + EXCEL_SUFFIX, StandardCharsets.UTF_8.name());
			response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
			// 把内容填充到输出流
			EasyExcel.write(response.getOutputStream(), ExportSensitiveWordDto.class).sheet("大头菜敏感词").doWrite(exportSensitiveWordDtos);
		} catch (Exception e) {
			log.error("批量导出敏感词-controller层-exportWords-异常", e);
		}
	}

	private List<ExportSensitiveWordDto> buildExportSensitiveWordDto(List<SensitiveWordDto> sensitiveWordDtos) {
		if (CollectionUtils.isEmpty(sensitiveWordDtos)) {
			return new ArrayList<>();
		}
		List<ExportSensitiveWordDto> targetList = new ArrayList<>();
		sensitiveWordDtos.forEach(sensitiveWordDto -> {
			ExportSensitiveWordDto target = new ExportSensitiveWordDto();
			BeanUtils.copyProperties(sensitiveWordDto, target);
			targetList.add(target);
		});
		return targetList;
	}

	/**
	 * 接口参数校验
	 * @param param
	 */
	private void checkParam(AddSensitiveWordParam param) {

		Assert.isTrue(param != null, "入参不能为空");
		Assert.isTrue(StringUtils.isNotBlank(param.getWord()), "敏感词不能为空");
		Assert.isTrue(StringUtils.isNotBlank(param.getCategory()), "类别不能为空");
	}
}
